package com.matrix.rabbitmqtest.deadqueue;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.matrix.rabbitmqtest.util.AppKeys;
import com.matrix.rabbitmqtest.util.RabbitMQUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

/**
 * 死信队列
 * 正常订单消费者
 */
public class OrderConsumer {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtil.getChannel();
        // 声明正常交换机, 队列和绑定关系
        channel.exchangeDeclare(AppKeys.NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.queueDeclare(AppKeys.NORMAL_QUEUE, false, false, false, new HashMap<String, Object>() {{
            // put("x-message-ttl", 10000); // TTL时常,一般不在此设置,而是在发布消息再指定
            put("x-dead-letter-exchange", AppKeys.DEAD_EXCHANGE); // 遇到死信转发给哪个交换机?
            put("x-dead-letter-routing-key", "dead"); // 以何种路由转发给这个交换机?
            put("x-max-length", 5); // 队列最大长度, 多的将直接进入死信队列
        }});
        channel.queueBind(AppKeys.NORMAL_QUEUE, AppKeys.NORMAL_EXCHANGE, "order");
        // 声明死信交换机, 队列和绑定关系
        channel.exchangeDeclare(AppKeys.DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.queueDeclare(AppKeys.DEAD_QUEUE, false, false, false, null);
        channel.queueBind(AppKeys.DEAD_QUEUE, AppKeys.DEAD_EXCHANGE, "dead");

        // 开始消费
        Console.log("开始等待订单以消费...");
        channel.basicConsume(AppKeys.NORMAL_QUEUE, false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, StandardCharsets.UTF_8);
                // 如果orderId中包含666, 则拒接消费
                if (StrUtil.contains(message, "666")) {
                    getChannel().basicReject(envelope.getDeliveryTag(), false); // 模拟消费失败
                    Console.error("已拒接订单: {}", message);
                    return;
                }
                Console.log("接收到订单: {}", message);
                getChannel().basicAck(envelope.getDeliveryTag(), false);
            }
        });
    }
}
